package yartiss.engine.simulation.scheduling.policies.fp;

import java.util.List;
import java.util.SortedSet;

import yartiss.engine.simulation.IEnergyProfile;
import yartiss.engine.simulation.ISchedulingPolicy;
import yartiss.engine.simulation.events.EventGenerator;
import yartiss.engine.simulation.scheduling.policies.AbstractMonoProcessorSchedulingPolicy;
import yartiss.engine.simulation.system.ITask;
import yartiss.engine.simulation.system.ITaskSet;
import yartiss.engine.simulation.system.taskset.TaskSetFactory;

/**
 * Preemptive Fixed Priority. When there is not enough energy, the system is
 * paused until the energy level reaches a threshold 
 */
public class EHPFP2SchedulingPolicy extends AbstractMonoProcessorSchedulingPolicy {

	private List<Integer> parameters;

	/**
	 * 
	 */
	@Override
	public String getPolicyName() {
		return "EH_PFP_2";
	}

	/**
	 * 
	 */
	@Override
	public void setParameters(List<Integer> parameters) {
		this.parameters = parameters;
	}
	
	@Override
	public List<Integer> getParameters() {
		return parameters;
	}

	@Override
	public ITaskSet createTaskSet() {
		return TaskSetFactory.getNewInstance("priority");
	}
	
	

	
	boolean paused = false;

	@Override
	public ITask chooseNextTask(ITaskSet taskSet, IEnergyProfile energyProfile,long date, EventGenerator evGen) {

		long energyMin = (energyProfile.getMaxEnergyLevel() - energyProfile.getMinEnergyLevel())* parameters.get(0)	/ 100+ energyProfile.getMinEnergyLevel();

		if (date == 0)
			paused = false; // pour lancer +sieurs simulation a la suite

		SortedSet<ITask> activeTasks = taskSet.getActiveTasks(date);

		if (!activeTasks.isEmpty() && (!paused || energyProfile.getCurrentEnergyLevel() >= energyMin)) {
			ITask first = activeTasks.first();
			paused = false;

			long hlcet = energyProfile.howLongCanExecute(first);

			if (hlcet <= 0 && energyProfile.getCurrentEnergyLevel() < energyMin) {
				paused = true;
				long x = (energyMin - energyProfile.getCurrentEnergyLevel())	/ energyProfile.getPowerRate();
				if (x == 0)
					x = 1;
				evGen.generateEvent("check_energy_state", activeTasks.first(), date+ x, null);
				return null;
			}

			if (hlcet <= 0) {
				evGen.generateEvent("check_energy_state", activeTasks.first(), date+ 1, null);
				return null;
			}

			if (hlcet < activeTasks.first().getRemainingCost())
				evGen.generateEvent("check_energy_state", activeTasks.first(), date+ hlcet, null);

			return activeTasks.first();
		}

		return null;
	}

	@Override
	public ISchedulingPolicy newInstance() {
		return new EHPFP2SchedulingPolicy();
	}
}
